Skip to content

fix(im): accept absolute paths for --image/--file flags#905

Open
EvanYao826 wants to merge 2 commits into
larksuite:mainfrom
EvanYao826:fix/accept-absolute-paths
Open

fix(im): accept absolute paths for --image/--file flags#905
EvanYao826 wants to merge 2 commits into
larksuite:mainfrom
EvanYao826:fix/accept-absolute-paths

Conversation

@EvanYao826
Copy link
Copy Markdown

@EvanYao826 EvanYao826 commented May 15, 2026

Summary

Fixes #872

The --image and --file flags on im +messages-send and im +messages-reply rejected absolute paths with a validation error. This is inconvenient for AI agents and scripted callers that construct absolute paths.

Changes

  • Added SafeAbsoluteInputPath() to validate package — validates absolute paths for safety (control characters, symlink resolution) without restricting to the working directory
  • Updated validateMediaFlagPath() to accept absolute paths after safety validation
  • Added openMediaFile/statMediaFile helpers in helpers.go that use os.Open/os.Stat for absolute paths and FileIO for relative paths
  • Updated help text for --image and --file flags to indicate absolute paths are accepted

Security

  • Absolute paths are still validated for control characters and symlink resolution
  • Relative paths continue to use FileIO which restricts to the working directory
  • The LocalFileIO.Open and LocalFileIO.Stat methods are unchanged — the security boundary is only relaxed for explicitly user-provided media flag values

Summary by CodeRabbit

  • New Features

    • Media upload flags now accept absolute and relative file paths.
    • CLI help text for image/file flags clarified to indicate absolute or relative path support.
  • Improvements

    • Added safer validation for absolute file paths (symlink-aware, rejects unsafe characters).
    • Local media upload now more reliably opens and checks local files, improving upload robustness.

Review Change Stack

The --image and --file flags on im +messages-send and +messages-reply
rejected absolute paths with a validation error. This is inconvenient
for AI agents and scripted callers that construct absolute paths.

Changes:
- Added SafeAbsoluteInputPath() to validate package for absolute paths
  that still checks control characters and resolves symlinks
- Updated validateMediaFlagPath() to accept absolute paths after safety
  validation
- Added openMediaFile/statMediaFile helpers that use os.Open/os.Stat
  for absolute paths and FileIO for relative paths
- Updated help text to indicate absolute paths are accepted

Fixes larksuite#872
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e1346e97-003d-4da0-a136-76fe5bceb01e

📥 Commits

Reviewing files that changed from the base of the PR and between d3b46ec and 82de8b6.

📒 Files selected for processing (1)
  • shortcuts/im/helpers.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • shortcuts/im/helpers.go

📝 Walkthrough

Walkthrough

Adds safe absolute-path validation and path-type-aware file I/O so IM --image/--file flags accept absolute or relative local paths; updates help text and validation to use the new validators and changes upload functions to open/stat absolute paths via the OS when appropriate.

Changes

Absolute Path Support for Media Flags

Layer / File(s) Summary
Absolute-path safety validators
internal/validate/path.go, internal/vfs/localfileio/path.go
Adds SafeAbsoluteInputPath and safePathAbsolute; SafeLocalFlagPath now routes absolute flag values to absolute-path validation while keeping existing relative-path checks.
Dual-mode media file handling
shortcuts/im/helpers.go
Adds openMediaFile and statMediaFile to use os.Open/os.Stat for absolute paths and runtime.FileIO() for relative paths; uploadImageToIM and uploadFileToIM now use these helpers.
Command integration and help text
shortcuts/im/im_messages_send.go, shortcuts/im/im_messages_reply.go
Update imports and flag descriptions to mention absolute or relative local file paths; validateMediaFlagPath validates absolute paths via validate.SafeAbsoluteInputPath.

Sequence Diagram

sequenceDiagram
  participant User
  participant CLI as im +messages-send
  participant Validator as validateMediaFlagPath
  participant SafeAbs as SafeAbsoluteInputPath
  participant FileIO as openMediaFile/statMediaFile
  participant OS as os / runtime.FileIO
  User->>CLI: --image /tmp/image.png
  CLI->>Validator: image value
  Validator->>SafeAbs: /tmp/image.png
  SafeAbs->>SafeAbs: reject control chars, resolve symlinks
  SafeAbs-->>Validator: validated path or error
  Validator-->>CLI: valid
  CLI->>FileIO: open/stat /tmp/image.png
  FileIO->>OS: use os.Open/os.Stat (absolute)
  OS-->>FileIO: file handle/info
  FileIO-->>CLI: ready for upload
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • larksuite/cli#322: Refactors media-flag validation in validateMediaFlagPath with FileIO-based checks; this PR extends the same validation to support absolute paths via SafeAbsoluteInputPath.

Suggested reviewers

  • MaxHuang22
  • liangshuo-1

Poem

🐰 I hop through paths both short and grand,
From ./file to /tmp at hand.
Symlinks checked and strange chars kept away,
Uploads ready whether near or far today! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: accepting absolute paths for --image/--file flags in the im commands.
Description check ✅ Passed The PR description provides a clear summary, comprehensive list of changes, security considerations, and links the related issue #872.
Linked Issues check ✅ Passed The implementation fulfills issue #872 by accepting absolute paths while maintaining security validation and updating help text to document the change.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #872: adding SafeAbsoluteInputPath validation, updating flag validation logic, and improving help text for --image/--file flags.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added domain/im PR touches the im domain size/M Single-domain feat or fix with limited business impact labels May 15, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
shortcuts/im/helpers.go (1)

571-594: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Duration parsing will fail for absolute audio/video paths.

parseMediaDuration calls runtime.FileIO().Stat() and runtime.FileIO().Open() (lines 575, 579), which reject absolute paths outside the working directory. For absolute audio/video files, duration parsing will fail silently (returning ""), causing uploads to succeed but omit the duration field.

🔧 Suggested fix

Refactor parseMediaDuration to use the dual-mode helpers:

 func parseMediaDuration(runtime *common.RuntimeContext, filePath, fileType string) string {
 	if fileType != "opus" && fileType != "mp4" {
 		return ""
 	}
-	info, err := runtime.FileIO().Stat(filePath)
+	info, err := statMediaFile(runtime, filePath)
 	if err != nil || info.Size() == 0 {
 		return ""
 	}
-	f, err := runtime.FileIO().Open(filePath)
+	f, err := openMediaFile(runtime, filePath)
 	if err != nil {
 		return ""
 	}
+	defer f.Close()

 	var ms int64
 	if fileType == "opus" {
-		ms = readOggDuration(f, info.Size())
+		ms = readOggDuration(f.(fileio.File), info.Size())
 	} else {
-		ms = readMp4Duration(f, info.Size())
+		ms = readMp4Duration(f.(fileio.File), info.Size())
 	}
 	if ms <= 0 {
 		return ""
 	}
 	return strconv.FormatInt(ms, 10)
 }

Note: You'll need to update readOggDuration and readMp4Duration to accept io.ReaderAt instead of fileio.File, or add type assertions as shown.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/im/helpers.go` around lines 571 - 594, parseMediaDuration currently
fails for absolute paths because it uses runtime.FileIO().Stat() and Open()
which reject absolute locations; refactor parseMediaDuration to use the
dual-mode file helpers (open a reader that supports both filesystem and external
absolute URLs) instead of directly calling runtime.FileIO().Stat/Open, and
update readOggDuration and readMp4Duration to accept a generic io.ReaderAt (or
perform a safe type assertion on the returned reader) so you can pass the reader
returned by the dual-mode helper; ensure ms calculation and error handling
remain the same in parseMediaDuration and return the formatted ms when >0.
🧹 Nitpick comments (1)
shortcuts/im/helpers.go (1)

1323-1334: ⚡ Quick win

Fragile type assertion could panic.

Line 1333 asserts fi.(os.FileInfo) without checking. If a test uses a custom FileIO implementation that returns a fileio.FileInfo not implementing os.FileInfo, this will panic.

♻️ Simpler signature

The callers only need .Size(), which is available on fileio.FileInfo. Change the return type:

-func statMediaFile(runtime *common.RuntimeContext, filePath string) (os.FileInfo, error) {
+func statMediaFile(runtime *common.RuntimeContext, filePath string) (fileio.FileInfo, error) {
 	if filepath.IsAbs(filePath) {
 		return os.Stat(filePath)
 	}
 	fi, err := runtime.FileIO().Stat(filePath)
 	if err != nil {
 		return nil, err
 	}
-	return fi.(os.FileInfo), nil
+	return fi, nil
 }

This avoids the assertion and works correctly with both real and mock FileIO.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/im/helpers.go` around lines 1323 - 1334, statMediaFile currently
returns os.FileInfo and does an unchecked type assertion fi.(os.FileInfo) which
can panic for custom FileIO implementations; change statMediaFile to return
fileio.FileInfo (or the common interface used by callers) and update its
signature on callers to use .Size(); for absolute paths adapt the os.Stat result
to fileio.FileInfo (add a small adapter type or converter that wraps an
os.FileInfo and implements fileio.FileInfo) and for the runtime.Path case return
the runtime.FileIO().Stat(filePath) value directly without asserting to
os.FileInfo.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@shortcuts/im/helpers.go`:
- Around line 1313-1334: Update the comments for openMediaFile and statMediaFile
to clearly state these helpers require paths to be pre-validated (e.g., by
validateMediaFlagPath) before being passed in; explicitly mention that absolute
paths are opened/sta'd with os.Open/os.Stat without further checks and that
callers must ensure the path is safe and validated to avoid security risks.
Reference the functions openMediaFile and statMediaFile and the validator
validateMediaFlagPath in the comment so future maintainers see the required
precondition and the reason (absolute paths bypass runtime.FileIO protections).

---

Outside diff comments:
In `@shortcuts/im/helpers.go`:
- Around line 571-594: parseMediaDuration currently fails for absolute paths
because it uses runtime.FileIO().Stat() and Open() which reject absolute
locations; refactor parseMediaDuration to use the dual-mode file helpers (open a
reader that supports both filesystem and external absolute URLs) instead of
directly calling runtime.FileIO().Stat/Open, and update readOggDuration and
readMp4Duration to accept a generic io.ReaderAt (or perform a safe type
assertion on the returned reader) so you can pass the reader returned by the
dual-mode helper; ensure ms calculation and error handling remain the same in
parseMediaDuration and return the formatted ms when >0.

---

Nitpick comments:
In `@shortcuts/im/helpers.go`:
- Around line 1323-1334: statMediaFile currently returns os.FileInfo and does an
unchecked type assertion fi.(os.FileInfo) which can panic for custom FileIO
implementations; change statMediaFile to return fileio.FileInfo (or the common
interface used by callers) and update its signature on callers to use .Size();
for absolute paths adapt the os.Stat result to fileio.FileInfo (add a small
adapter type or converter that wraps an os.FileInfo and implements
fileio.FileInfo) and for the runtime.Path case return the
runtime.FileIO().Stat(filePath) value directly without asserting to os.FileInfo.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1ccb1ba-6e7a-4360-8311-d95cd27a9ce3

📥 Commits

Reviewing files that changed from the base of the PR and between 4a45e00 and d3b46ec.

📒 Files selected for processing (5)
  • internal/validate/path.go
  • internal/vfs/localfileio/path.go
  • shortcuts/im/helpers.go
  • shortcuts/im/im_messages_reply.go
  • shortcuts/im/im_messages_send.go

Comment thread shortcuts/im/helpers.go Outdated
Address CodeRabbit review: document that callers must validate paths
before calling these helpers, since they use os.Open/os.Stat directly
for absolute paths without additional safety checks.
@EvanYao826
Copy link
Copy Markdown
Author

@CLAassistant recheck please

@EvanYao826
Copy link
Copy Markdown
Author

@CLAassistant recheck

1 similar comment
@EvanYao826
Copy link
Copy Markdown
Author

@CLAassistant recheck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/im PR touches the im domain size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--image / --file flags reject absolute paths but --help doesn't document this

2 participants